#include <format>
#include <initializer_list>
#include <iostream>
#include <sstream>
#include <string>

// 辅助函数，用于将参数转换为字符串
template <typename T> std::string paramToString(const T &param) {
  std::ostringstream oss;
  oss << param;
  if (oss.fail()) {
    std::cerr << "Error converting parameter to string." << std::endl;
    return "";
  }
  return oss.str();
}

// 辅助函数，用于将多个参数转换为逗号分隔的字符串
template <typename... Args> std::string argsToString(Args... args) {
  std::ostringstream oss;
  bool first = true;
  for (const auto &argStr : {paramToString(args)...}) {
    if (!first) {
      oss << ", ";
    }
    oss << argStr;
    first = false;
  }
  return oss.str();
}

// 定义一个类，用于记录函数的开始和结束，并包含参数及其值
class FunctionLogger {
public:
  FunctionLogger(const std::string &name, const std::string &args)
      : funcName(name), exceptionMsg("") {
    std::cout << "Function Start: " << funcName << "(" << args << ")"
              << std::endl;
  }

  ~FunctionLogger() {
    if (exceptionMsg.empty()) {
      std::cout << "Function End (Normal): " << funcName << std::endl;
    } else {
      std::cout << "Function End (Abnormal): " << funcName
                << ", Reason: " << exceptionMsg << std::endl;
    }
  }

  void setException(const std::string &msg) { exceptionMsg = msg; }

private:
  std::string funcName;
  std::string exceptionMsg;
};

// 定义一个宏，用于调用 FunctionLogger
#define LOG_FUNCTION_START_END(...)                                            \
  FunctionLogger loggerInstance(__func__, argsToString(__VA_ARGS__));          \
  auto setException = [&](const std::string &msg) {                            \
    loggerInstance.setException(msg);                                          \
  };

#define LOG_FUNCTION_EXCEPTION(...) setException(__VA_ARGS__);
// 示例函数
void exampleFunction(int a, double b, const std::string &c) {
  LOG_FUNCTION_START_END(a, b, c); // 插入宏并传入参数
  if (a < 0) {
    LOG_FUNCTION_EXCEPTION(std::format("Parameter 'a:{}' is less than 0", a));
    return;
  }
  std::cout << "Executing inside the function." << std::endl;
}

int main() {
  std::cout << "Starting program..." << std::endl;
  exampleFunction(42, 3.14, "Hello");
  exampleFunction(-1, 3.14, "Hello");
  std::cout << "Program finished." << std::endl;
  return 0;
}